Skip to content

Hibernate inactive terminal tabs to bound long-session resource use - #709

Merged
sbertix merged 7 commits into
mainfrom
sbertix/gh-680-hibernate-inactive-terminal-surfaces-to
Jul 22, 2026
Merged

Hibernate inactive terminal tabs to bound long-session resource use#709
sbertix merged 7 commits into
mainfrom
sbertix/gh-680-hibernate-inactive-terminal-surfaces-to

Conversation

@sbertix

@sbertix sbertix commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Closes #680

Summary

Hidden terminal tabs (background tabs of the selected worktree and all tabs of
deselected worktrees) now release their Ghostty surfaces after five minutes of
being hidden. The zmx sessions survive untouched, and selecting the tab
rebuilds the layout with the original surface UUIDs so every pane reattaches
in place with its screen, scrollback, and running processes intact. This
bounds the memory, CPU, and process count of long-lived sessions instead of
letting every open tab hold a live terminal forever.

  • Agents keep running through hibernation: their processes live in the zmx
    session, and a passive per-session watcher keeps OSC signals lossless while
    dormant, so notifications (OSC 9), agent presence (OSC 3008), and titles
    still arrive and unseen-notification counters survive the dark period.
  • Hibernated tabs and fully hibernated worktrees show a zzz indicator in
    the tab bar and sidebar.
  • Gated behind a Beta toggle in General > Advanced, on by default, with a
    single default source of truth so pre-feature settings files decode to on.

Known tradeoffs: the handoff between a live surface and its watcher has a
millisecond-scale window at hibernate and wake (a signal can be lost or, far
more rarely, a 3008 notification duplicated), waking a session whose process
died spawns a fresh shell, and turning the toggle off does not force-wake
already-dormant tabs; they wake on selection.

Type of change

  • Bug fix (the linked issue is a bug report)
  • Feature (the linked issue is a feature request marked ready)
  • Documentation
  • Other (please describe)

How was this tested?

Unit coverage for the hibernation state machine (eligibility, teardown
bookkeeping, wake paths, dormant OSC ingestion, watcher lifecycle, flag
gating, and persistence round-trips) plus watcher tests against a fake socket
server. Verified live by hibernating and waking real agent sessions.

  • make check passes (format + lint)
  • make test passes
  • I built and ran the app to confirm the change works

Checklist

  • This pull request is linked to an issue with Closes # above.
  • For a feature, the linked issue is labeled ready.
  • I am the author of this work and accountable for it; no commit is authored or co-authored by an AI agent.
  • I have read the Contributing guide and the Code of Conduct.

sbertix added 4 commits July 22, 2026 00:02
Hidden tabs release their Ghostty surfaces after five minutes; the zmx
sessions survive and selecting the tab rebuilds the layout with the
original surface UUIDs so sessions reattach in place. Agents keep
running through hibernation, and dormant sessions keep routing OSC
notifications, agent presence, and titles through the passive watchers.
@sbertix
sbertix enabled auto-merge (squash) July 21, 2026 22:05
sbertix added 3 commits July 22, 2026 00:39
…ate-inactive-terminal-surfaces-to

# Conflicts:
#	supacode/Features/Terminal/BusinessLogic/WorktreeTerminalManager.swift
#	supacode/Features/Terminal/Models/WorktreeTerminalState.swift
#	supacodeTests/SettingsFeatureTests.swift
Jumping to a hibernated tab's notification wakes it, selects its worktree, and
lands keyboard focus in the terminal. A partial wake now logs its own error and
falls back to whatever the tab rebuilt instead of stranding a woken tab with
nothing focused.

Closing a hibernated tab always confirms: it has no live surface to ask, and
waking one to read its prompt state races the zmx replay. The reason rides on
the pending confirmation so the copy names what was actually found, and a tab
holding a pending alert no longer hibernates underneath it.
…ate-inactive-terminal-surfaces-to

# Conflicts:
#	SupacodeSettingsShared/Models/GlobalSettings.swift
#	supacodeTests/SettingsFilePersistenceTests.swift
@sbertix
sbertix merged commit b718aff into main Jul 22, 2026
3 checks passed
@sbertix
sbertix deleted the sbertix/gh-680-hibernate-inactive-terminal-surfaces-to branch July 22, 2026 08:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hibernate inactive terminal surfaces to bound long-session resource use

1 participant